<?php

declare(strict_types=1);

namespace So\Aspect;

use Hyperf\Contract\ConfigInterface;
use Hyperf\Di\Annotation\Inject;
use So\Annotation\Model as ModelAnnotation;
use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use So\Request;
use So\Response;

/**
 * 切入Model注解实现模型注入
 * @Aspect
 * @author Saopig <1306222220@qq.com>
 */
class Model extends AbstractAspect
{

    /**
     * @Inject()
     * @var Response
     */
    protected $response;

    /**
     * @Inject()
     * @var ConfigInterface
     */
    protected $config;

    /**
     * @Inject()
     * @var Request
     */
    protected $request;

    /**
     * @var string[]
     */
    public $annotations = [
        ModelAnnotation::class,
    ];

    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
        $classname = array_filter(explode("\\", $proceedingJoinPoint->className));
        $names = ['Controller', 'Service', 'Logic'];
        foreach ($classname as $k => &$v) {
            if (($k + 1) !== count($classname)) {
                in_array($v, $names) && $v = 'Model';
            }else{
                $v = str_replace($names, '', $v);
            }
        }
        $model = implode("\\",$classname);
        $Annotation = $proceedingJoinPoint->getAnnotationMetadata();
        $ModelAnnotation = $Annotation->method[ModelAnnotation::class] ?? [];
        $query = $ModelAnnotation->query;
        $var = $ModelAnnotation->var;
        $exception = $this->config->get('so.exception.model');
        if (!class_exists($model)) {
            if ($exception) {
                throw new $exception('Model is not defined');
            }
            return $this->response->error('Model is not defined');
        }
        $model = $query ? make($model)::query() : make($model);
        $proceedingJoinPoint->arguments['keys'][$var] = $model;
        return $proceedingJoinPoint->process();
    }

}